﻿using System;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.Security.Principal;
using InfoJetSoft.Service.Entity;
using InfoJetSoft.Service.Worker;

namespace InfoJetSoft.Service.Util
{

    public class ExtXdXDocFunction : IExtensionFunctions
	{
		private Form form = null;

		public ExtXdXDocFunction( Form frm ){
			this.form = frm;
		}

        //CID 1031 //2011.11.24 //Begin
        private XPathNodeIterator xmlDocNodeIterator = null;
        //CID 1031 //2011.11.24 //End

        //CID 1031 //2011.11.24 //Begin
        public void SetXmlDocNodeIterator()
        {
            XPathNavigator navi = this.form.XmlDoc.CreateNavigator();
            this.xmlDocNodeIterator = navi.Select(".");
        }
        //CID 1031 //2011.11.24 //End

        //CID 1031 //2011.11.24 //Begin
        public void ClearXmlDocNodeIterator()
        {
            this.xmlDocNodeIterator = null;
        }
        //CID 1031 //2011.11.24 //End

        //CID 0755 //2011.01.14 //Begin
        #region IExtensionFunction Members

        public string Prefix
        {
            get { return this.form.Manifest.NsResolver.GetPrefix(this.NamespaceURI); }
        }

        public string NamespaceURI
        {
            get { return JetConstant.URI_XDXDOC; }
        }

        public IXsltContextFunction ResolveFunction(string prefix, string name, XPathResultType[] argTypes)
        {
            //CID 0839 //2011.03.26 //Begin
            if (name.Equals("getDOM"))
            {
                return new XPathFunction(this.form, prefix, name, 0, 0, argTypes, XPathResultType.NodeSet);
            }
            else if (name.Equals("GetDOM"))
            {
                return new XPathFunction(this.form, prefix, name, 1, 1, argTypes, XPathResultType.NodeSet);
            }
            else if (name.Equals("getUserName"))
            {
                return new XPathFunction(this.form, prefix, name, 0, 0, argTypes, XPathResultType.String);
            }
            else if (name.Equals("getRole"))
            {
                return new XPathFunction(this.form, prefix, name, 0, 0, argTypes, XPathResultType.String);
            }
            else if (name.Equals("GetNamedNodeProperty"))
            {
                return new XPathFunction(this.form, prefix, name, 3, 3, argTypes, XPathResultType.String);
            }
            else
            {
                throw new InfoJetException("Unimplemented Function.", prefix + ":" + name);
            }
            //CID 0839 //2011.03.26 //End
        }

        public object InvokeFunction(string prefix, string name, XsltContext xsltContext, object[] args, XPathNavigator docContext)
        {
            //CID 0839 //2011.03.26 //Begin
            if (name.Equals("getDOM"))
            {
                return this.getDOM();
            }
            else if (name.Equals("GetDOM"))
            {
                return this.GetDOM((string)args[0]);
            }
            else if (name.Equals("getUserName"))
            {
                return this.getUserName();
            }
            else if (name.Equals("getRole"))
            {
                return this.getRole();
            }
            else if (name.Equals("GetNamedNodeProperty"))
            {
                return this.GetNamedNodeProperty(args[0], args[1], args[2]);
            }
            else
            {
                throw new InfoJetException("Unimplemented Function.", prefix + ":" + name);
            }
            //CID 0839 //2011.03.26 //End
        }

        #endregion
        //CID 0755 //2011.01.14 //End

        public XPathNodeIterator getDOM()
        {
            //CID 1031 //2011.11.24 //Begin
            if (this.xmlDocNodeIterator != null)
            {
                return this.xmlDocNodeIterator;
            }
            else
            {
                XPathNavigator navi = this.form.XmlDoc.CreateNavigator();
                return navi.Select("/");
            }
            //CID 1031 //2011.11.24 //End
        }

		public XPathNodeIterator GetDOM( string dataObjectName )
		{
			XmlDocument dataDoc = FormDataLoadWorker.GetXmlDoc( this.form, dataObjectName );
			XPathNavigator navi = dataDoc.CreateNavigator();
			return navi.Select( "/" );
		}

		public string getUserName()
		{
			//优先使用API指定的UserName.
			if( this.form.JetContext.UserName != null && this.form.JetContext.UserName.Length > 0 )
			{
				return this.form.JetContext.UserName;
			}
			return System.Environment.UserName;
		}
		
		public string getRole()
		{
			//优先使用API指定的UserRole.
			if( this.form.JetContext.UserRole != null && this.form.JetContext.UserRole.Length > 0 )
			{
				return this.form.JetContext.UserRole;
			}

			Roles roles = this.form.Manifest.Roles;
			if( roles != null )
			{
				if( roles.Initiator != null )
				{
					if( this.form.Command.Equals( JetConstant.CMD_BUILD_BY_TEMPLATE ) )
					{
						return roles.Initiator;
					}
					string initiatorForm = (string)form.ParamTable[ JetConstant.XDOC_PARAM_INITIATOR_FORM ];
					if( initiatorForm != null && initiatorForm.Equals( JetConstant.YES ) )
					{
						return roles.Initiator;
					}
				}

				string memberOf = null;

				if( roles.MembershipList != null )
				{
					foreach( Membership membership in roles.MembershipList )
					{
						if( membership.Type == Membership.UserName )
						{
							string userName = WindowsIdentity.GetCurrent().Name;
							bool found = false;
							foreach( string name in membership.NameList )
							{
								if( name.ToLower().Equals( userName.ToLower() ) )
								{
									memberOf = membership.MemberOf;
									found = true;
									break;// break the loop of NameList.
								}
							}
							if( found )
							{
								break;// break the loop of MembershipList
							}
						}
						if( membership.Type == Membership.Group )
						{
							WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());
							bool found = false;
							foreach( string name in membership.NameList )
							{
								if( wp.IsInRole( name ) )
								{
									memberOf = membership.MemberOf;
									found = true;
									break;
								}
							}
							if( found )
							{
								break;// break the loop of 
							}
						}
						if( membership.Type == Membership.GetUserNameFromData )
						{
							XmlDocument doc = null;
							NamespaceResolver nsResolver = null;
							if( membership.DataObject == null )
							{
								doc = this.form.XmlDoc;
								nsResolver = this.form.XmlNsResolver;
							}
							else
							{
								doc = FormDataLoadWorker.loadDataObjectByName( this.form, membership.DataObject );
								nsResolver = new NamespaceResolver( doc );
							}
							if( doc != null )
							{
								String userName = WindowsIdentity.GetCurrent().Name;
								XmlNodeList nameNodeList = doc.SelectNodes( membership.Select, nsResolver );
								bool found = false;
								foreach( XmlNode nameNode in nameNodeList )
								{
									String name = DOMUtil.getNodeValue( nameNode ).Trim();
									if( name.ToLower().Equals( userName.ToLower() ) )
									{
										memberOf = membership.MemberOf;
										found = true;
										break;// break the loop of nameNodeList.
									}
								}
								if( found )
								{
									break;// break the loop of MembershipList.
								}
							}
						}
					}
				}

				if( memberOf == null )
				{
					memberOf = roles.DefaultRole;
				}
 
				return memberOf;
			}

			return "";
		}

		//xdXDocument:GetNamedNodeProperty(/my:myFields/my:group1, 'CTRL1_5', 1)
		public string GetNamedNodeProperty(System.Object param1, System.Object param2, System.Object param3) 
		{
            //CID 0749 //2011.08.29 //Begin
            if (param2 is string)
            {
                string action = param2 as string;
                if (action.Equals("CanAddSignature"))
                {
                    if (form.SignedDataInfoList != null)
                    {
                        XPathNodeIterator nodeIterator = (XPathNodeIterator)param1;
                        if (nodeIterator.MoveNext())
                        {
                            XmlNode currentNode = ((System.Xml.IHasXmlNode)nodeIterator.Current).GetNode();
                            foreach (SignedDataInfo signedDataInfo in form.SignedDataInfoList)
                            {
                                if (signedDataInfo.ContainerElement.Equals(currentNode))
                                {
                                    //CID 1039 //2012.01.06 //Begin
                                    if (signedDataInfo.Mode.Equals("single"))
                                    {
                                        if (signedDataInfo.SignatureElementList.Count > 0)
                                        {
                                            return "false";
                                        }
                                    }
                                    if (signedDataInfo.Mode.Equals("countersign"))
                                    {
                                        foreach (SignedElementInfo elementInfo in signedDataInfo.SignatureElementList)
                                        {
                                            if (elementInfo.Status != SignedStatus.NotTrusted && elementInfo.Status != SignedStatus.Expired)
                                            {
                                                return "false";
                                            }
                                        }
                                    }
                                    //CID 1039 //2012.01.06 //End
                                    break;
                                }
                            }
                        }
                        return "true";
                    }
                    else
                    {
                        return "true";
                    }
                }
                else if (action.Equals("IsValidSignature"))
                {
                    if (form.SignedDataInfoList != null)
                    {
                        XPathNodeIterator nodeIterator = (XPathNodeIterator)param1;
                        if (nodeIterator.MoveNext())
                        {
                            XmlNode currentNode = ((System.Xml.IHasXmlNode)nodeIterator.Current).GetNode();
                            foreach (SignedDataInfo signedDataInfo in form.SignedDataInfoList)
                            {
                                foreach (SignedElementInfo signedElementInfo in signedDataInfo.SignatureElementList)
                                {
                                    if (signedElementInfo.SignatureElement.Equals(currentNode))
                                    {
                                        //CID 1030 //2012.01.05 //Begin
                                        if (signedDataInfo.HasExtraSignature)
                                        {
                                            return "false";
                                        }
                                        //CID 1030 //2012.01.05 //End
                                        //CID 1021 //2011.09.29 //Begin
                                        if (signedElementInfo.Status == SignedStatus.Valid)
                                        {
                                            return "true";
                                        }
                                        else
                                        {
                                            return "false";
                                        }
                                        //CID 1021 //2011.09.29 //End
                                    }
                                }
                            }
                        }
                    }
                    return "false";
                }
                //CID 0749 //2011.09.10 //Begin
                else if (action.Equals("IsSigned"))
                {
                    if (form.SignedDataInfoList != null)
                    {
                        XPathNodeIterator nodeIterator = (XPathNodeIterator)param1;
                        if (nodeIterator.MoveNext())
                        {
                            XmlNode currentNode = ((System.Xml.IHasXmlNode)nodeIterator.Current).GetNode();
                            foreach (SignedDataInfo signedDataInfo in form.SignedDataInfoList)
                            {
                                if (signedDataInfo.ContainerElement.Equals(currentNode))
                                {
                                    if (signedDataInfo.SignatureElementList.Count > 0)
                                    {
                                        return "true";
                                    }
                                }
                            }
                        }
                    }
                    return "false";
                }
                //CID 0749 //2011.09.10 //End
                //CID 0749 //2011.09.16 //Begin
                else if (action.Equals("CanDeleteSignature"))
                {
                    if (form.SignedDataInfoList != null)
                    {
                        XPathNodeIterator nodeIterator = (XPathNodeIterator)param1;
                        if (nodeIterator.MoveNext())
                        {
                            XmlNode currentNode = ((System.Xml.IHasXmlNode)nodeIterator.Current).GetNode();
                            foreach (SignedDataInfo signedDataInfo in form.SignedDataInfoList)
                            {
                                foreach (SignedElementInfo signedElementInfo in signedDataInfo.SignatureElementList)
                                {
                                    if (signedElementInfo.SignatureElement.Equals(currentNode))
                                    {
                                        if (signedDataInfo.Mode.Equals("countersign"))
                                        {
                                            if (signedDataInfo.SignatureElementList.Count > 1)
                                            {
                                                if (signedDataInfo.SignatureElementList.IndexOf(signedElementInfo) == (signedDataInfo.SignatureElementList.Count - 1))
                                                {
                                                    return "true";
                                                }
                                                else
                                                {
                                                    return "false";
                                                }
                                            }
                                            else
                                            {
                                                return "true";
                                            }
                                        }
                                        else
                                        {
                                            return "true";
                                        }
                                    }
                                }
                            }
                        }
                    }
                    return param3 as string;
                }
                else if (action.Equals("SignedBy"))
                {
                    if (form.SignedDataInfoList != null)
                    {
                        XPathNodeIterator nodeIterator = (XPathNodeIterator)param1;
                        if (nodeIterator.MoveNext())
                        {
                            XmlNode currentNode = ((System.Xml.IHasXmlNode)nodeIterator.Current).GetNode();
                            foreach (SignedDataInfo signedDataInfo in form.SignedDataInfoList)
                            {
                                foreach (SignedElementInfo signedElementInfo in signedDataInfo.SignatureElementList)
                                {
                                    if (signedElementInfo.SignatureElement.Equals(currentNode))
                                    {
                                        return signedElementInfo.SignedBy;
                                    }
                                }
                            }
                        }
                    }
                    return param3 as string;
                }
                else if (action.Equals("SignedOn"))
                {
                    if (form.SignedDataInfoList != null)
                    {
                        XPathNodeIterator nodeIterator = (XPathNodeIterator)param1;
                        if (nodeIterator.MoveNext())
                        {
                            XmlNode currentNode = ((System.Xml.IHasXmlNode)nodeIterator.Current).GetNode();
                            foreach (SignedDataInfo signedDataInfo in form.SignedDataInfoList)
                            {
                                foreach (SignedElementInfo signedElementInfo in signedDataInfo.SignatureElementList)
                                {
                                    if (signedElementInfo.SignatureElement.Equals(currentNode))
                                    {
                                        return signedElementInfo.SignedOn;
                                    }
                                }
                            }
                        }
                    }
                    return param3 as string;
                }
                //CID 0749 //2011.09.16 //End
            }
            //CID 0749 //2011.09.05 //End
			if (param1 is XPathNodeIterator) 
			{
				//Xslt中传递来的控件名，如CTRL1_5。
				string controlName = (string) param2;
				double order = 0;
				if( param3 is double )
				{
					order = (double)param3;
				}
				else
				{
					try
					{
						order = double.Parse((string)param3);
					}
					catch( Exception e )
					{
						return "false";
					}
				}
				//从HTTP提交参数中获取当前MasterDetail的标记，其中包含行号信息，如CTRL1_5,2;CTRL10_5,1。
				string masterDetialValue = (string) form.ParamTable[JetConstant.XDOC_PARAM_MASTER_DETIAL];
				if (masterDetialValue == null || masterDetialValue.Length <= 0) 
				{
					return order + "";
				}
				StringTokenizer masterDetialTokenizer = new StringTokenizer(masterDetialValue, JetConstant.ID_SEPARATOR);
				while (masterDetialTokenizer.HasMoreTokens()) 
				{
					string masterDetial = (string) masterDetialTokenizer.NextToken();
					StringTokenizer nameRowTokenizer = new StringTokenizer(masterDetial, JetConstant.INNER_SEPARATOR);
					string name = nameRowTokenizer.NextToken();
					string row = nameRowTokenizer.NextToken();
					//找到匹配的控件，使用它的对应的行号。
					if (name.Equals(controlName)) 
					{
						return row;
					}
				}
				return order + "";
			}
			return "1";
        }

        //CID 1503 //2012.12.22 //Begin
        public string HasSignatureLine(string ctrlId)
        {
            if (form.View.SignatureLines != null)
            {
                foreach (SignatureLine signatureLine in form.View.SignatureLines)
                {
                    if (signatureLine.Name.Equals(ctrlId))
                    {
                        if (form.SignedDataInfoList != null)
                        {
                            foreach (SignedDataInfo signedDataInfo in form.SignedDataInfoList)
                            {
                                foreach (SignedElementInfo elementInfo in signedDataInfo.SignatureElementList)
                                {
                                    XmlElement signatureLineElement = QuickSelectUtil.SelectChildElementByLocalNameSteps(elementInfo.SignatureElement, new String[] { "Object", "SignatureLine" });
                                    if (signatureLineElement != null)
                                    {
                                        string sigCtrlId = signatureLineElement.GetAttribute("name");
                                        if (sigCtrlId.Equals(ctrlId))
                                        {
                                            return "true";
                                        }
                                    }
                                }
                            }
                        }
                        break;
                    }
                }
            }
            return "false";
        }
        //CID 1503 //2012.12.22 //End

        //CID 1503 //2012.12.22 //Begin
        public XPathNodeIterator GetSignatureLineElement(string ctrlId)
        {
            XmlElement lastSignatureLineElement = null;
            if (form.View.SignatureLines != null)
            {
                foreach (SignatureLine signatureLine in form.View.SignatureLines)
                {
                    if (signatureLine.Name.Equals(ctrlId))
                    {
                        if (form.SignedDataInfoList != null)
                        {
                            foreach (SignedDataInfo signedDataInfo in form.SignedDataInfoList)
                            {
                                foreach (SignedElementInfo elementInfo in signedDataInfo.SignatureElementList)
                                {
                                    XmlElement signatureLineElement = QuickSelectUtil.SelectChildElementByLocalNameSteps(elementInfo.SignatureElement, new String[] { "Object", "SignatureLine" });
                                    if (signatureLineElement != null)
                                    {
                                        string sigCtrlId = signatureLineElement.GetAttribute("name");
                                        if (sigCtrlId.Equals(ctrlId))
                                        {
                                            lastSignatureLineElement = elementInfo.SignatureElement;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (lastSignatureLineElement != null)
            {
                XPathNavigator nav = lastSignatureLineElement.CreateNavigator();
                return nav.Select(".");
            }
            else
            {
                return null;
            }
        }
        //CID 1503 //2012.12.22 //End
    }
}